// Dwarf.Unmanaged.Serial.cpp : Defines the entry point for the console application.
//

#include "Dwarf.Unmanaged.Mpi.h"

using namespace std;

// The settings for this dwarf.
static Settings* settings;

// Get settings from the command line.
static int getSettings(int argc, char** argv, Solver *clsolver) 
{
    int error = 0;
    if (clsolver->isRootThread) 
    {
        settings = new Settings();
        if (settings->init(argc,argv,clsolver))     //Parse all arguments for dwarf.
        {            
            delete settings;
            error = 1;
        }
    }    

    //Distribute error if that occurred while parsing.
    MPI_Bcast(&error, 1, MPI_INT, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD); 

    if (error) return -1;

    if (clsolver->isRootThread) 
    {
        clsolver->bufferSize = min( max(clsolver->length / ((clsolver->commSize - 1) * 8 * 10), 1), MAX_BLOCK_SIZE);
    }

    //Distribute number of bytes for each process.
    MPI_Bcast(&clsolver->bufferSize, 1, MPI_UNSIGNED, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD); 
    
    return 0;
}

// Point of the program start.
void main(int argc, char** argv)
{   

    Solver* clsolver = new Solver(); 

    if (clsolver->commSize == 1) 
    {
        delete clsolver;
        printf("Only one mpi process.");
        exit(-1);
    }

    if (getSettings(argc, argv, clsolver))         // Get settings from the command line.
    {
        delete clsolver;
        exit(-1);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    if (clsolver->isRootThread) 
    {
        settings->start();                          // Start new time count.
    }

	clsolver->solve();                             // Solve the current problem.

    MPI_Barrier(MPI_COMM_WORLD);

    if (clsolver->isRootThread) 
    {
        settings->finish(clsolver);                // Stop the time count and write results.
        delete settings;
    }

    delete clsolver;
}